package cn.autumnorange.app.common.dto;

import cn.autumnorange.app.common.core.treeservice.TreeClassService;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

public abstract class BaseTreeDto<E extends BaseTreeDto> extends BaseDto
    implements TreeClassService<E, String>
//        , UpDownTreeDtoService<E>
{
  private String parentId;
  private TreeSet<E> children;
  //  同级排序
  private int sort;

  @Override
  public String getParentId() {
    return parentId;
  }

  @Override
  public void setParentId(String parentId) {
    this.parentId = parentId;
  }

  @Override
  public TreeSet<E> getChildren() {
    return children;
  }

  @Override
  public void setChildren(TreeSet<E> children) {
    if (children == null) {
      children =
          new TreeSet<E>(
              new Comparator<E>() {
                @Override
                public int compare(E o1, E o2) {
                  if (!StringUtils.equals(o1.getParentId(), o2.getParentId())) {
                    throw new RuntimeException("同一级别添加错误");
                  }
                  if (o1.getId().equals(o2.getId())) {
                    return 0;
                  }
                  int sort = o1.getSort() - o2.getSort();
                  if (sort == 0) {
                    return 1;
                  }
                  return sort;
                }
              });
    }
    this.children = children;
  }

  @Override
  public int getSort() {
    return this.sort;
  }

  @Override
  public void setSort(int sort) {
    this.sort = sort;
  }

  public static <E extends BaseTreeDto> TreeSet<E> upDownTreeEntity(List<E> treeEntityCollection) {
    if (treeEntityCollection.size() > 1) {
      HashSet<E> vertexSet = new HashSet<E>();
      //      还是要考虑多个顶级菜单
      //      菜单集合剩余都是顶点菜单集则排序结束

      while (!vertexSet.containsAll(treeEntityCollection)) {
        E vertexBaseTreeEntity = null;
        for (int i = 0; i < treeEntityCollection.size(); i++) {
          vertexBaseTreeEntity = treeEntityCollection.get(i);
          if (!vertexSet.contains(vertexBaseTreeEntity)) {
            break;
          }
        }
        //        顶点菜单赋予其所有下级菜单并从菜单集合去除其所有下级菜单
        setChildren(vertexBaseTreeEntity, treeEntityCollection);
        //     首选顶点菜单可能会存在上级需要重新加回来
        //                treeEntityCollection.add(vertexBaseTreeEntity);
        //        每个作为顶点菜单都有可能包含之前所有作为顶点菜单的顶点
        //        检验顶点菜单集合是否有被作其上级顶点菜单包含了
        Iterator<E> vertexBaseTreeEntityIterator = vertexSet.iterator();
        while (vertexBaseTreeEntityIterator.hasNext()) {
          BaseTreeDto checkVertexBaseTreeEntity = vertexBaseTreeEntityIterator.next();
          //          如果剩余菜单已经不存在顶点菜单则已经有其上级顶点菜单包含了需要移除其作为顶点菜单资格
          if (!treeEntityCollection.contains(checkVertexBaseTreeEntity)) {
            vertexBaseTreeEntityIterator.remove();
          }
        }
        //        新顶点菜单
        vertexSet.add(vertexBaseTreeEntity);
      }

      TreeSet<E> realVertexSet =
          new TreeSet<E>(
              new Comparator<E>() {
                @Override
                public int compare(E o1, E o2) {
                  if (o2.getId().equals(o1.getId())) {
                    return 0;
                  }
                  if (o1.getSort() - o2.getSort() == 0) {
                    return 1;
                  }
                  return o1.getSort() - o2.getSort();
                }
              });
      realVertexSet.addAll(vertexSet);
      return realVertexSet;
    }
    return null;
  }

  public static <E extends BaseTreeDto> void setChildren(
      E upLevelBaseTreeEntity, Collection<E> treeEntityList) {
    if (upLevelBaseTreeEntity.getChildren() == null) {
      upLevelBaseTreeEntity.setChildren(null);
    }
    Iterator<E> iterator = treeEntityList.iterator();
    while (iterator.hasNext()) {
      E children = iterator.next();
      if (upLevelBaseTreeEntity.getId().equals(children.getParentId())) {
        upLevelBaseTreeEntity.getChildren().add(children);
        iterator.remove();
      }
    }
    TreeSet<E> upLevelBaseTreeEntityChildren = upLevelBaseTreeEntity.getChildren();
    if (upLevelBaseTreeEntityChildren == null) {
      return;
    }
    for (E sysRoleEntity : upLevelBaseTreeEntityChildren) {
      setChildren(sysRoleEntity, treeEntityList);
    }
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof BaseTreeDto)) return false;
    if (!super.equals(o)) return false;
    BaseTreeDto<?> that = (BaseTreeDto<?>) o;
    return this.getId().equals(((BaseTreeDto<?>) o).getId());
  }

  @Override
  public int hashCode() {

    return Objects.hash(super.hashCode(), parentId, children, sort);
  }
}
